Skip to content

fix: handle string-typed reviewer.id in ruleset API responses#3341

Open
dpwspoon-hi wants to merge 1 commit intointegrations:mainfrom
dpwspoon-hi:fix/ruleset-reviewer-string-id
Open

fix: handle string-typed reviewer.id in ruleset API responses#3341
dpwspoon-hi wants to merge 1 commit intointegrations:mainfrom
dpwspoon-hi:fix/ruleset-reviewer-string-id

Conversation

@dpwspoon-hi
Copy link
Copy Markdown

@dpwspoon-hi dpwspoon-hi commented Apr 16, 2026

Summary

Fixes #3340 and #3214

The GitHub API returns required_reviewers.reviewer.id as a JSON string (e.g., "12345"), but go-github's RulesetReviewer.ID field is *int64. Standard Go JSON unmarshaling rejects this with:

json: cannot unmarshal string into Go struct field RepositoryRuleset.rules.required_reviewers.reviewer.id of type int64

The POST/PUT succeeds (the ruleset is created/updated on GitHub), but the provider cannot parse the response — so the resource is never recorded in Terraform state, creating orphaned rulesets on every retry.

Why existing tests didn't catch this

The acceptance test TestAccGithubRepositoryRuleset_requiredReviewers (added in #3073) only runs when a maintainer adds the acctest label, and the CI matrix (anonymous, individual, organization) requires an org-mode run to pass the skipUnlessHasOrgs precheck. The unit tests for expandRequiredReviewers / flattenRequiredReviewers only exercise in-memory Go struct round-trips — they never parse raw JSON from the API, so they never hit the string→int64 mismatch that lives inside go-github's json.Unmarshal path.

Approach

Rather than patching go-github upstream, this adds thin wrapper functions around the ruleset CRUD API calls in util_rules.go. The wrappers use client.BareDo() to obtain the raw HTTP response body, apply a targeted regex ("id"\s*:\s*"(\d+)""id":$1) to convert quoted integer IDs to unquoted integers, then unmarshal into the standard go-github types.

This approach:

  • Fixes both repository-level and organization-level rulesets
  • Is safe because the only "id" field returned as a quoted integer in ruleset responses is reviewer.id (the top-level ruleset ID and other numeric fields are already returned as JSON numbers)
  • Matches the URL construction and method signatures of the upstream go-github methods exactly
  • Does not affect any other API calls

Changes

  • github/util_rules.go: Added fixReviewerStringIDs() regex helper, doRulesetRequest() for raw response handling, and 6 wrapper functions (createRepoRuleset, getRepoRuleset, updateRepoRuleset, createOrgRuleset, getOrgRuleset, updateOrgRuleset)
  • github/resource_github_repository_ruleset.go: Replaced 4 direct go-github calls with wrapper functions
  • github/resource_github_organization_ruleset.go: Replaced 4 direct go-github calls with wrapper functions
  • github/util_rules_test.go: Added unit tests for fixReviewerStringIDs (7 cases) and an end-to-end unmarshal round-trip test that simulates the actual buggy API response

Test plan

  • Unit tests for fixReviewerStringIDs covering: quoted integer conversion, unquoted passthrough, no-space formatting, multiple IDs, non-digit strings, empty strings, full nested response
  • End-to-end unmarshal test simulating the actual GitHub API response with string reviewer IDs — verifies the fix at the JSON layer where the bug actually occurs
  • Existing TestExpandRequiredReviewers, TestFlattenRequiredReviewers, TestRoundTripRequiredReviewers still pass
  • go vet ./... clean
  • Full build succeeds
  • Acceptance test TestAccGithubRepositoryRuleset_requiredReviewers — requires acctest label + org-mode CI run to exercise the real API round-trip

The GitHub API returns `required_reviewers.reviewer.id` as a JSON
string (e.g., `"12345"`), but go-github's `RulesetReviewer.ID` field
is `*int64`. This causes `json.Unmarshal` to fail, preventing the
provider from recording the resource in state after creation — leading
to orphaned rulesets on every retry.

Work around this by replacing direct go-github API calls for ruleset
CRUD with thin wrappers that use `client.BareDo` to obtain the raw
response body, apply a regex fix to convert quoted integer IDs to
unquoted integers, and then unmarshal into the go-github types.

Fixes integrations#3340

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions github-actions bot added the Type: Bug Something isn't working as documented label Apr 16, 2026
@github-actions
Copy link
Copy Markdown

👋 Hi! Thank you for this contribution! Just to let you know, our GitHub SDK team does a round of issue and PR reviews twice a week, every Monday and Friday! We have a process in place for prioritizing and responding to your input. Because you are a part of this community please feel free to comment, add to, or pick up any issues/PRs that are labeled with Status: Up for grabs. You & others like you are the reason all of this works! So thank you & happy coding! 🚀

@dpwspoon-hi dpwspoon-hi marked this pull request as ready for review April 16, 2026 15:53
Copy link
Copy Markdown
Collaborator

@deiga deiga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, but we will not accept hacky workarounds for possible issues in go-github. Either find a reasonable way to fix it in the provider or submit a PR to go-github

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Awaiting response Type: Bug Something isn't working as documented

Projects

None yet

Development

Successfully merging this pull request may close these issues.

github_repository_ruleset: required_reviewers reviewer.id fails with 'cannot unmarshal string into int64'

2 participants